<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>摹图3D模型</title>
    <!-- 引入 Vue -->
    <script src="https://unpkg.com/vue@2.6.14/dist/vue.js"></script>
    <!-- 引入 Element UI CSS -->
    <link rel="stylesheet" href="https://unpkg.com/element-ui@2.15.14/lib/theme-chalk/index.css">
    <!-- 引入 Element UI JavaScript -->
    <script src="https://unpkg.com/element-ui@2.15.14/lib/index.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.12.2/gsap.min.js"></script>

    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            background-color: #000;
            color: #fff;
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
        }

        .container {
            display: flex;
            min-height: 100vh;
        }

        .sidebar {
            width: 200px;
            background-color: #1a1a1a;
            padding: 20px;
        }

        .logo {
            margin-bottom: 30px;
        }

        .logo img {
            width: 120px;
        }

        .menu-item {
            padding: 12px;
            color: #fff;
            text-decoration: none;
            display: flex;
            align-items: center;
            margin-bottom: 10px;
            border-radius: 6px;
        }

        .menu-item:hover {
            background-color: #333;
        }

        .menu-item i {
            margin-right: 10px;
        }

        .main-content {
            flex: 1;
            padding: 20px;
        }

        .header {
            display: flex;
            justify-content: flex-end;
            align-items: center;
            margin-bottom: 30px;
        }

        .credits {
            margin-right: 20px;
            padding: 8px 16px;
            background-color: #333;
            border-radius: 20px;
        }

        .model-grid {
            display: grid;
            /*grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));*/
            gap: 20px;
            margin-bottom: 40px;
        }

        .model-card {
            background-color: #1a1a1a;
            border-radius: 8px;
            overflow: hidden;
            aspect-ratio: 1;
        }

        model-viewer {
            width: 100%;
            height: 100%;
            background-color: #000;
        }

        .upload-section {
            padding: 20px;
            border: 2px dashed #333;
            border-radius: 8px;
            text-align: center;
            margin-top: 40px;
        }



        .button {
            background-color: #ffd700;
            color: #000;
            padding: 12px 24px;
            border: none;
            border-radius: 6px;
            cursor: pointer;
            font-weight: bold;
        }

        .button:hover {
            background-color: #ffed4a;
        }


        .model-grid {
            position: relative;
            overflow: hidden;
        }

        .model-card-container {
            display: flex;
            overflow-x: hidden;
            scroll-behavior: smooth;
        }

        .model-card {
            flex: 0 0 auto;
            width: 350px; /* 设置每个卡片的大小 */
            height: 250px; /* 设置每个卡片的大小 */
            margin-right: 10px; /* 卡片之间的间距 */
        }

        .canvas-wrapper {
            position: relative;
            width: 100%;
            height: 100%;
            background: radial-gradient(ellipse at center, rgba(255,255,255,0.3) 20%, rgba(0,0,0,1) 110%);
        }



        .canvas-wrapper canvas {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: transparent; /* 确保 canvas 自身背景透明 */
        }



        .scroll-button {
            position: absolute;
            top: 50%;
            transform: translateY(-50%);
            background-color: rgba(0, 0, 0, 0.5);
            color: white;
            border: none;
            cursor: pointer;
            padding: 10px;
            z-index: 10;
        }

        .scroll-button.left {
            left: 10px;
        }

        .scroll-button.right {
            right: 10px;
        }
        .el-upload-dragger {
            background-color: black;
        }

        .el-textarea__inner{
            background-color: black;
        }


        .custom-button {
            margin-top: 20px;
            background-color: #ffd200; /* 按钮背景色 */
            color: #000; /* 按钮文字颜色 */
            font-weight: bold; /* 文字加粗 */
            border-radius: 15px; /* 圆角 */
            height: 40px; /* 高度 */
            align-items: center;
            justify-content: space-between;
            width: 200px;
            border: none;
        }

        .custom-button:hover,
        .custom-button:focus,
        .custom-button:active {
            background-color: #ffd200; /* 按钮背景色 */
            color: #000; /* 按钮文字颜色 */
            font-weight: bold; /* 文字加粗 */
            border-radius: 15px; /* 圆角 */
            height: 40px; /* 高度 */
            align-items: center;
            justify-content: space-between;
            border: none;
        }


        .custom-icon {
            display: flex;
            align-items: center;
            gap: 5px; /* 图标和文字间距 */
        }

        .icon-lightning {
            width: 14px;
            height: 14px;
            display: inline-block;
        }

        .dimmed-text {
            color: rgba(0, 0, 0, 0.4); /* 灰色文字 */
            font-size: 0.9em;
        }

        .center-container {
            display: flex;
            justify-content: center;
        }

        .el-dialog__body {
            height: 460px; /* 设置 body 的高度 */
        }

        /*.el-dialog{*/
        /*    background-color: #666666;*/
        /*}*/



        .avatar-uploader .el-upload {
            border: 1px dashed #d9d9d9;
            border-radius: 6px;
            cursor: pointer;
            position: relative;
            overflow: hidden;
        }
        .avatar-uploader .el-upload:hover {
            border-color: #409EFF;
        }
        .avatar-uploader-icon {
            font-size: 28px;
            color: #8c939d;
            width: 178px;
            height: 178px;
            line-height: 178px;
            text-align: center;
        }
        .avatar {
            width: 178px;
            height: 178px;
            display: block;
        }


        .canvas-wrapper {
            position: relative;
            width: 100%;
            height: 100%;
            transition: transform 0.3s ease;
            perspective: 800px; /* 提供3D透视效果 */
        }

        .canvas-wrapper:hover {
            transform: scale(1.1); /* 悬浮时放大 */
        }



    </style>
    <!-- 添加 Three.js 相关库 -->
    <!-- 将 CDN 引用改为本地文件 -->
    <script src="./public/js/three/three.min.js"></script>
    <script src="./public/js/three/OrbitControls.js"></script>
    <script src="./public/js/three/GLTFLoader.js"></script>
    <script src="./public/js/three/OBJLoader.js"></script>
    <script src="./public/js/three/MTLLoader.js"></script>
</head>
<body>
    <div class="container" id="app1">
        <div class="sidebar">
            <div class="logo">
                <img src="public/logo.png" alt="Logo">
            </div>
            <a href="#" class="menu-item">
                <i>🏠</i>
                首页
            </a>
            <a href="indexMy.html" class="menu-item">
                <i>📁</i>
                我的模型
            </a>
        </div>

        <div class="main-content">
            <div class="header">
                <div class="credits">
                    <span>💰 {{yue}}</span>
                </div>
                <div class="credits" style="cursor:pointer" @click="chongzhi">
                    <span>充值</span>
                </div>
                <div class="credits" style="cursor:pointer" @click="exit">
                    <span>切换账号</span>
                </div>
            </div>
            <div class="model-grid">
                <button class="scroll-button left" onclick="scrollModels('left')">‹</button>
                <div class="model-card-container">
                    <div class="model-card">
                        <div class="canvas-wrapper">
                            <canvas id="canvas1" style="width: 100%; height: 100%;" onmouseover="this.style.cursor='pointer'" data-url="indexShow.html"  data-path="./moxing/zly.glb"></canvas>
                        </div>
                    </div>
                    <div class="model-card">
                        <div class="canvas-wrapper">
                            <canvas id="canvas2" style="width: 100%; height: 100%;" onmouseover="this.style.cursor='pointer'" data-url="indexShow.html"  data-path="./moxing/abm.glb"></canvas>
                        </div>
                    </div>
                    <div class="model-card">
                        <div class="canvas-wrapper">
                            <canvas id="canvas3" style="width: 100%; height: 100%;" onmouseover="this.style.cursor='pointer'" data-url="indexShow.html"  data-path="./moxing/gql.glb"></canvas>
                        </div>
                    </div>
                    <div class="model-card">
                        <div class="canvas-wrapper">
                            <canvas id="canvas4" style="width: 100%; height: 100%;" onmouseover="this.style.cursor='pointer'" data-url="indexShow.html"  data-path="./moxing/lyf2.glb"></canvas>
                        </div>
                    </div>
                    <div class="model-card">
                        <div class="canvas-wrapper">
                            <canvas id="canvas5" style="width: 100%; height: 100%;" onmouseover="this.style.cursor='pointer'" data-url="indexShow.html"  data-path="./moxing/zzx.glb"></canvas>
                        </div>
                    </div>
                    <div class="model-card">
                        <div class="canvas-wrapper">
                            <canvas id="canvas6" style="width: 100%; height: 100%;" onmouseover="this.style.cursor='pointer'" data-url="indexShow.html"  data-path="./moxing/tlp.glb"></canvas>
                        </div>
                    </div>
                </div>
                <button class="scroll-button right" onclick="scrollModels('right')">›</button>
            </div>

<!--            <script>-->
<!--                class ModelViewer {-->
<!--                    constructor(canvasId) {-->
<!--                        this.canvas = document.getElementById(canvasId);-->
<!--                        this.init();-->
<!--                    }-->

<!--                    init() {-->
<!--                        // 创建场景-->
<!--                        this.scene = new THREE.Scene();-->
<!--                        this.scene.background = null;-->

<!--                        // 创建相机-->
<!--                        this.camera = new THREE.PerspectiveCamera(-->
<!--                            75,-->
<!--                            this.canvas.clientWidth / this.canvas.clientHeight,-->
<!--                            0.1,-->
<!--                            1000-->
<!--                        );-->
<!--                        this.camera.position.z = 5;-->

<!--                        // 创建渲染器-->
<!--                        this.renderer = new THREE.WebGLRenderer({-->
<!--                            canvas: this.canvas,-->
<!--                            antialias: true, alpha: true-->
<!--                        });-->
<!--                        this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);-->
<!--                        this.renderer.setClearColor(0x000000, 0);-->
<!--                        this.renderer.setPixelRatio(window.devicePixelRatio);-->

<!--                        // 添加控制器-->
<!--                        this.controls = new THREE.OrbitControls(this.camera, this.canvas);-->
<!--                        this.controls.enableDamping = true;-->
<!--                        this.controls.enableZoom = false;   // 禁用缩放-->

<!--                        // 修改灯光设置-->
<!--                        // 增加环境光强度-->
<!--                        const ambientLight = new THREE.AmbientLight(0x404040, 1.0); // 将强度从 0.5 提升到 1.0-->
<!--                        this.scene.add(ambientLight);-->

<!--                        // 添加多个平行光源-->
<!--                        const directionalLight1 = new THREE.DirectionalLight(0xffffff, 1.0);-->
<!--                        directionalLight1.position.set(0, 1, 1);-->
<!--                        this.scene.add(directionalLight1);-->

<!--                        const directionalLight2 = new THREE.DirectionalLight(0xffffff, 0.8);-->
<!--                        directionalLight2.position.set(1, 1, -1);-->
<!--                        this.scene.add(directionalLight2);-->

<!--                        const directionalLight3 = new THREE.DirectionalLight(0xffffff, 0.6);-->
<!--                        directionalLight3.position.set(-1, 1, 0);-->
<!--                        this.scene.add(directionalLight3);-->

<!--                        // 添加半球光-->
<!--                        const hemiLight = new THREE.HemisphereLight(0xffffff, 0x444444, 0.8);-->
<!--                        hemiLight.position.set(0, 1, 0);-->
<!--                        this.scene.add(hemiLight);-->

<!--                        // 设置渲染器的色调映射-->
<!--                        this.renderer.toneMapping = THREE.ACESFilmicToneMapping;-->
<!--                        this.renderer.toneMappingExposure = 1.2;-->
<!--                        this.renderer.outputEncoding = THREE.sRGBEncoding;-->

<!--                        // 开始动画循环-->
<!--                        this.animate();-->

<!--                        // 处理窗口大小变化-->
<!--                        window.addEventListener('resize', () => this.onWindowResize());-->
<!--                    }-->

<!--                    loadModel(url) {-->

<!--                        const loader = new THREE.GLTFLoader();-->
<!--                        loader.load(url, (gltf) => {-->
<!--                            this.scene.add(gltf.scene);-->
<!--                            this.fitCameraToObject(gltf.scene);-->
<!--                        });-->
<!--                    }-->

<!--                    fitCameraToObject(object) {-->
<!--                        const box = new THREE.Box3().setFromObject(object);-->
<!--                        const center = box.getCenter(new THREE.Vector3());-->
<!--                        const size = box.getSize(new THREE.Vector3());-->

<!--                        const maxDim = Math.max(size.x, size.y, size.z);-->
<!--                        const fov = this.camera.fov * (Math.PI / 180);-->
<!--                        let cameraZ = Math.abs(maxDim / 2 / Math.tan(fov / 2));-->

<!--                        this.camera.position.z = cameraZ * 1.5;-->
<!--                        this.controls.target.copy(center);-->
<!--                        this.controls.update();-->
<!--                    }-->

<!--                    animate() {-->
<!--                        requestAnimationFrame(() => this.animate());-->
<!--                        this.controls.update();-->
<!--                        this.renderer.render(this.scene, this.camera);-->
<!--                    }-->

<!--                    onWindowResize() {-->
<!--                        this.camera.aspect = this.canvas.clientWidth / this.canvas.clientHeight;-->
<!--                        this.camera.updateProjectionMatrix();-->
<!--                        this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);-->
<!--                    }-->
<!--                }-->

<!--                // 创建模型查看器实例-->
<!--                const viewer1 = new ModelViewer('canvas1');-->
<!--                const viewer2 = new ModelViewer('canvas2');-->
<!--                const viewer3 = new ModelViewer('canvas3');-->
<!--                const viewer4 = new ModelViewer('canvas4');-->
<!--                const viewer5 = new ModelViewer('canvas5');-->
<!--                const viewer6 = new ModelViewer('canvas6');-->

<!--                // 加载模型-->
<!--                viewer1.loadModel('http://117.131.189.172:8105/get-glb-file/1737897708721'); // 可以是 .glb, .gltf, .obj 等格式-->
<!--                viewer2.loadModel('http://117.131.189.172:8105/get-glb-file/1737897476242');-->
<!--                viewer3.loadModel('http://117.131.189.172:8105/get-glb-file/1737897209740');-->
<!--                viewer4.loadModel('http://117.131.189.172:8105/get-glb-file/1737896970908');-->
<!--                viewer5.loadModel('http://117.131.189.172:8105/get-glb-file/1737896703926');-->
<!--                viewer6.loadModel('http://117.131.189.172:8105/get-glb-file/1737815244733');-->
<!--            </script>-->
            <div class="upload-section">
                <div style="display: flex; flex-direction: column; align-items: flex-start; margin-bottom: 20px;">
                    <el-radio v-model="radio" label="1">图片生成</el-radio>
                    <el-radio v-model="radio" label="2" style="margin-top: 10px;">文本生成</el-radio>
                </div>

<!--                <el-upload-->
<!--                        v-if="radio==1"-->
<!--                        class="upload-wrap"-->
<!--                        drag-->
<!--                        :show-file-list="false"-->
<!--                >-->
<!--                    <div style="padding-top: 35px">-->
<!--                        <img src="./moxing/uploadIcon.png" style="height: 25px; width: auto" />-->
<!--                        <div class="el-upload__text" style="font-size: 11px; margin-top: 10px">要求:上传服装正面平铺图，平整无遮挡、无折叠</div>-->
<!--                    </div>-->
<!--                </el-upload>-->
                <el-upload
                        v-if="radio==1"
                        class="avatar-uploader"
                        action="#"
                        :show-file-list="false"
                        :on-change="handleImageChange"
                        :auto-upload="false">
                    <img v-if="imageUrl" :src="imageUrl" class="avatar">
                    <i v-else class="el-icon-plus avatar-uploader-icon"></i>
                </el-upload>
                <div v-if="!imageUrl&&radio=='1'">点击上传</div>
                <div v-if="!imageUrl&&radio=='1'">支持png、jpg格式</div>
                <el-input
                        v-if="radio==2"
                        type="textarea"
                        :rows="4"
                        style="width: 500px"
                        placeholder="请输入内容"
                        v-model="textarea">
                </el-input>
            </div>

            <div class="center-container">
                <el-button class="custom-button" @click="zhixing">
                    生成3D模型
                    <img src="/public/sd.png" alt="icon" class="button-icon" />20
                </el-button>
            </div>

        </div>
        <el-dialog :visible.sync="dialogVisible" width="30%" title="生成结果">
            <div ref="loadingTarget" style="height: 100%; display: flex; justify-content: center; align-items: center;">
                <div ref="viewer" style="height: 100%;" v-if="dialogVisible"  onmouseover="this.style.cursor='pointer'" onclick="openModelInNewTab('indexShow.html',1,1)"></div>
            </div>
        </el-dialog>
        <el-dialog :visible.sync="chongzhiVisible" width="50%" title="充值">
            <div style="font-weight: bolder;text-align: center;font-size: 20px">请扫码联系服务人员</div>
            <div style="text-align: center;">
                <el-image
                        src="public/lx.png"
                        alt="Logo"
                        style="max-width: 40%; height: auto;">
                </el-image>
            </div>
        </el-dialog>
        <el-dialog
                :show-close="false"
                :visible.sync="dialogVisible1"
                width="35%"
                center
                custom-class="login-dialog login-dialog1"
                modal-class="custom-modal"
                :close-on-click-modal="false"
        >
            <div slot="title" class="custom-title">登录摹图3D模型平台</div>

            <section  class="form-section">
                <el-row type="flex" justify="center" style="margin-top: 40px;padding: 0 40px 0 40px">
                    <el-col>
                        <label class="form-label" style="width:420px ">用户名</label>
                        <el-input v-model="username" placeholder="请输入账号" ></el-input>
                    </el-col>
                </el-row>

                <el-row type="flex" justify="center"  style="margin-top: 50px;padding: 0 40px 0 40px">
                    <el-col>
                        <label class="form-label">密码</label>
                        <el-input placeholder="请输入密码" v-model="password"  show-password></el-input>
                    </el-col>
                </el-row>
            </section>

            <footer style="position: absolute; bottom: 10%; width: 100%;padding: 0 50px 0 40px;">
                <span class="comfy-user-error">&nbsp;</span>
                <div style="padding: 0 40px 0 0;">
                    <el-button type="primary" style="width: 100%;background-color: rgba(35, 82, 216, 1);" @click="login" >登录</el-button>
                </div>
            </footer>
            </form>
        </el-dialog>
    </div>

    <script>

        new Vue({
            el: '#app1',
            data() {
                return {
                    radio:'1',
                    textarea:'',
                    dialogVisible:false,
                    dialogVisible1:false,
                    loadingInstance:'',
                    renderer: null,
                    scene: null,
                    camera: null,
                    model: null,
                    controls:null,
                    imageUrl: '',
                    imageFile: null,
                    imageFileName:'',
                    username: '',
                    password: '',
                    loadingVisible:false,
                    yue:0,
                    num:20,
                    chongzhiVisible:false,
                    canvas:null,
                };
            },
            created(){

            },
            mounted() {
                this.handleLogin();
                class ModelViewer {
                    constructor(canvasId) {
                        this.canvas = document.getElementById(canvasId);
                        // this.canvas.style.width='100%';
                        // this.canvas.style.width='100%';
                        this.init();
                    }

                    init() {
                        let that=this;
                        // 创建场景
                        this.scene = new THREE.Scene();
                        this.scene.background = null;

                        // 创建相机
                        this.camera = new THREE.PerspectiveCamera(
                            75,
                            this.canvas.clientWidth / this.canvas.clientHeight,
                            0.1,
                            1000
                        );
                        this.camera.position.z = 5;

                        // 创建渲染器
                        this.renderer = new THREE.WebGLRenderer({
                            canvas: this.canvas,
                            antialias: true, alpha: true
                        });
                        this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
                        this.renderer.setClearColor(0x000000, 0);
                        this.renderer.setPixelRatio(window.devicePixelRatio);

                        // 添加控制器
                        this.controls = new THREE.OrbitControls(this.camera, this.canvas);
                        this.controls.enableZoom = false;
                        this.controls.enableDamping = true;


                        // 设置渲染器的色调映射
                        this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
                        this.renderer.toneMappingExposure = 1;
                        this.renderer.outputEncoding = THREE.sRGBEncoding;

                        // 开始动画循环
                        this.animate();

                        // 处理窗口大小变化
                        window.addEventListener('resize', () => this.onWindowResize());

                    }

                    loadModel(url) {

                        const loader = new THREE.GLTFLoader();
                        loader.load(url, (gltf) => {

                            let model = gltf.scene;


                            // 替换所有网格的材质为 MeshBasicMaterial，实现不受光照影响的“自发光”效果
                            model.traverse((node) => {
                                if (node.isMesh) {
                                    const originalMat = node.material;
                                    // 如果模型使用贴图，则在新材质中保留贴图
                                    if (originalMat.map) {
                                        node.material = new THREE.MeshBasicMaterial({
                                            map: originalMat.map,
                                            color: originalMat.color,
                                            // 如果原材质中有透明度、透明度测试等属性，可根据需要补充
                                            transparent: originalMat.transparent,
                                            opacity: originalMat.opacity
                                        });
                                    } else {
                                        node.material = new THREE.MeshBasicMaterial({
                                            color: originalMat.color
                                        });
                                    }
                                }
                            });



                            this.scene.add(gltf.scene);
                            this.fitCameraToObject(gltf.scene);
                        });
                    }

                    fitCameraToObject(object) {
                        const box = new THREE.Box3().setFromObject(object);
                        const center = box.getCenter(new THREE.Vector3());
                        const size = box.getSize(new THREE.Vector3());

                        const maxDim = Math.max(size.x, size.y, size.z);
                        const fov = this.camera.fov * (Math.PI / 180);
                        let cameraZ = Math.abs(maxDim / 2 / Math.tan(fov / 2));

                        this.camera.position.z = cameraZ * 1.5;
                        this.controls.target.copy(center);
                        this.controls.update();
                    }

                    animate() {
                        requestAnimationFrame(() => this.animate());
                        this.controls.update();
                        this.renderer.render(this.scene, this.camera);
                    }

                    onWindowResize() {
                        this.camera.aspect = this.canvas.clientWidth / this.canvas.clientHeight;
                        this.camera.updateProjectionMatrix();
                        this.renderer.setSize(this.canvas.clientWidth, this.canvas.clientHeight);
                    }
                }

                // 创建模型查看器实例
                const viewer1 = new ModelViewer('canvas1');
                const viewer2 = new ModelViewer('canvas2');
                const viewer3 = new ModelViewer('canvas3');
                const viewer4 = new ModelViewer('canvas4');
                const viewer5 = new ModelViewer('canvas5');
                const viewer6 = new ModelViewer('canvas6');

                // 加载模型
                viewer1.loadModel('./moxing/zly.glb'); // 可以是 .glb, .gltf, .obj 等格式
                viewer2.loadModel('./moxing/abm.glb');
                viewer3.loadModel('./moxing/gql.glb');
                viewer4.loadModel('./moxing/lyf2.glb');
                viewer5.loadModel('./moxing/zzx.glb');
                viewer6.loadModel('./moxing/tlp.glb');


            },
            methods: {
                async zhixing(){
                    var that=this;
                    if(this.radio=='1'){
                        //图片执行
                        if (!this.imageFile) {
                            this.$message.error('请先上传图片');
                            return;
                        }
                        if(this.yue<20){
                            this.$message.warning('余额不足，请充值！');
                            return false;
                        }
                        this.dialogVisible=true;
                        setTimeout(()=>{
                            this.startLoading();
                        },500)

                        let kt=await this.koutu();


                        if(kt!='ok'){
                            that.dialogVisible=false;
                            that.stopLoading();
                            return false;
                        }

                        // 创建 FormData 对象
                        const formData = new FormData();
                        formData.append('image', this.imageFile);
                        formData.append('user',localStorage.username);

                        try {
                            // 发送 POST 请求
                            let url='http://117.131.189.172:8105/api/generate3d/image';
                            const response = await fetch(url,{
                                method: 'POST', // 指定请求方法为 POST
                                body: formData // 将数据转换为 JSON 字符串
                            });
                            const loginObj = await response.json();
                            if(loginObj.taskId){
                                var t1 = setInterval(async function () {
                                    try {
                                        const response1 = await fetch('http://117.131.189.172:8105/api/progress/'+loginObj.taskId);
                                        const obj = await response1.json();
                                        if (obj.status=='completed') {
                                            clearInterval(t1)
                                            let url='http://117.131.189.172:8105/get-glb-file/'+loginObj.taskId;
                                            localStorage.glbUrl=url;
                                            that.initThreeJS(url);
                                            that.stopLoading();
                                            that.koufei();
                                        }
                                        if (obj.message.indexOf('执行失败')!=-1) {
                                            that.$message.error('生成失败');
                                            clearInterval(t1)
                                        }
                                    } catch (error) {
                                        console.log(error);
                                        clearInterval(t1)
                                    }
                                }, 10000)
                            }

                        } catch (error) {
                            this.$message.error('生成失败');
                            console.error(error);
                        }


                    }
                    if(this.radio=='2'){
                        //文本执行
                        if(!this.textarea){
                            this.$message.warning('请输入文本');
                            return false;
                        }
                        if(this.yue<20){
                            this.$message.warning('余额不足，请充值！');
                            return false;
                        }
                        this.dialogVisible=true;
                        setTimeout(()=>{
                            this.startLoading();
                        },500)
                        const loginResponse = await fetch('http://117.131.189.172:8105/api/generate3d?t1='+this.textarea+'&user='+localStorage.username);
                        const loginObj = await loginResponse.json();
                        if(loginObj.taskId){
                            var t1 = setInterval(async function () {
                                try {
                                    const response1 = await fetch('http://117.131.189.172:8105/api/progress/'+loginObj.taskId);
                                    const obj = await response1.json();
                                    if (obj.status=='completed') {
                                        clearInterval(t1)
                                        let url='http://117.131.189.172:8105/get-glb-file/'+loginObj.taskId;
                                        localStorage.glbUrl=url;
                                        that.initThreeJS(url);
                                        that.stopLoading();
                                        that.koufei();
                                    }
                                    if (obj.message.indexOf('执行失败')!=-1) {
                                        that.$message.error('生成失败');
                                        clearInterval(t1)
                                    }
                                } catch (error) {
                                    console.log(error);
                                    clearInterval(t1)
                                }
                            }, 10000)
                        }
                    }
                },
                startLoading() {
                    this.loadingInstance = this.$loading({
                        text: "生成中，请稍等~",
                        target: this.$refs.loadingTarget,
                        fullscreen: false,
                    });
                },
                stopLoading() {
                    if (this.loadingInstance) {
                        this.loadingInstance.close();
                    }
                },
                initThreeJS(url) {
                    let that=this;
                    const container = this.$refs.viewer;
                    container.style.width = '100%'; // 确保容器有大小
                    container.style.height = '400px'; // 可以根据需要调整高度
                    const width = container.clientWidth;
                    const height = container.clientHeight;

                    // 初始化渲染器
                    this.renderer = new window.THREE.WebGLRenderer({ antialias: true, alpha: true });
                    this.renderer.setSize(width, height);
                    this.renderer.setClearColor(0x000000, 0);
                    container.appendChild(this.renderer.domElement);

                    // 初始化场景
                    this.scene = new window.THREE.Scene();

                    // 初始化相机
                    this.camera = new window.THREE.PerspectiveCamera(75, width / height, 0.1, 1000);


                    // 设置渲染器的色调映射
                    this.renderer.toneMapping = THREE.ACESFilmicToneMapping;
                    this.renderer.toneMappingExposure = 1.2;
                    this.renderer.outputEncoding = THREE.sRGBEncoding;

                    // 加载GLB模型
                    const loader = new window.THREE.GLTFLoader();
                    loader.load(url, (gltf) => {
                        that.model = gltf.scene;

                            // 替换所有网格的材质为 MeshBasicMaterial，实现不受光照影响的“自发光”效果
                            that.model.traverse((node) => {
                                if (node.isMesh) {
                                    const originalMat = node.material;
                                    // 如果模型使用贴图，则在新材质中保留贴图
                                    if (originalMat.map) {
                                        node.material = new THREE.MeshBasicMaterial({
                                            map: originalMat.map,
                                            color: originalMat.color,
                                            // 如果原材质中有透明度、透明度测试等属性，可根据需要补充
                                            transparent: originalMat.transparent,
                                            opacity: originalMat.opacity
                                        });
                                    } else {
                                        node.material = new THREE.MeshBasicMaterial({
                                            color: originalMat.color
                                        });
                                    }
                                }
                            });

                        that.scene.add(that.model);
                        that.camera.position.z = 1.5;
                        that.animate();
                    },
                        (progress) => {
                            console.log(`Loading progress: ${(progress.loaded / progress.total) * 100}%`);
                        },
                        (error) => {
                            console.error('Error loading model:', error);
                        });

                },
                animate() {
                    requestAnimationFrame(this.animate);
                    this.renderer.render(this.scene, this.camera);
                },
                handleImageChange(file) {
                    // 读取图片文件并展示
                    const reader = new FileReader();
                    reader.onload = (e) => {
                        this.imageUrl = e.target.result;
                    };
                    reader.readAsDataURL(file.raw);

                    console.log(this.imageUrl);
                    // 保存文件对象
                    this.imageFile = file.raw;
                    this.imageFileName=file.name;
                    console.log(this.imageFile);
                },
                async login(){
                    var that=this
                    if (this.username==''){
                        this.$message.warning("请输入用户名~")
                        return false
                    }
                    if (this.password==''){
                        this.$message.warning("请输入密码~")
                        return false
                    }
                    try {
                        const loginResponse = await fetch('http://117.131.189.172:8096/login?username='+this.username+'&password='+this.password);
                        const loginObj = await loginResponse.json();
                        if(loginObj&&!loginObj.error){
                            that.loadingVisible=false;
                            // 登录成功的处理逻辑，例如保存token和id，并显示提示信息
                            // alert(JSON.stringify(response))
                            localStorage.setItem('token', loginObj.token);
                            localStorage.setItem('id', loginObj.id);
                            localStorage.setItem('username', that.username);
                            localStorage.setItem('is_admin',loginObj.is_admin);

                            that.is_admin=loginObj.is_admin=='1'?true:false;
                            that.$message.success("登录成功!")
                            that.getYuE();
                            that.dialogVisible1=false;
                        }else{
                            if(loginObj.error=='Token has expired'){
                                that.$message.error("登录失败，用户已过期！")
                                return;
                            }
                            that.$message.error("登录失败!")
                        }
                    }catch (e) {
                        that.$message.error("登录失败!")
                        console.log(e);
                    }
                },
                handleLogin() {
                    var that=this
                    // 这里可以编写实际登录验证逻辑，比如发送请求到后端等
                    if (localStorage.token==undefined||localStorage.token===''){
                        this.dialogVisible1=true
                    }else{
                        this.getYuE();
                    }
                },
                async koufei(){
                    const res = await fetch('http://117.131.189.172:8096/subtract3DCoins?userId='+localStorage.username+'&num='+this.num);
                    const obj = await res.json();
                    this.getYuE();
                    this.$message.success('操作成功');
                },
                async getYuE(){
                    const res = await fetch('http://117.131.189.172:8096/get3DCoins?username='+localStorage.username);
                    const obj = await res.json();
                    this.yue=obj.coins;
                    localStorage.yue=obj.coins;
                },

                async exit() {
                    // 构建确认消息
                    const message = `是否退出？`;
                    // 弹出确认对话框
                    const confirm = await this.$confirm(message, '确认操作', {
                        confirmButtonText: '确定',
                        cancelButtonText: '取消',
                        type: 'warning'
                    }).catch(err => err);

                    if (confirm === 'confirm') {
                        localStorage.token = ''
                        window.location.reload()
                    }

                },
                async chongzhi() {
                    this.chongzhiVisible=true;
                },


                async koutu() {
                    return new Promise(async (resolve, reject) => {
                        var that=this;
                        try {
                            var g1 = 'clo'
                            var requestData = {
                                "imageUrl": this.imageUrl,
                                "fuwuqi":'8288'
                            }
                            const responseComupload = await fetch('http://www.chenfuzhizao.com.cn/comupload8288',{
                                method:'POST',
                                headers: {
                                    'Content-Type': 'application/json' // 指定 JSON 格式
                                },
                                body: JSON.stringify(requestData)
                            });
                            let json1= await responseComupload.json();
                            console.log(json1);
                            var qpath = json1.name
                            var requestData2 = {"img1": qpath, "prompt": g1}
                            const responset2 = await fetch('http://www.chenfuzhizao.com.cn/compromptkoutuNot',
                                {method:'POST',
                                    headers: {
                                        'Content-Type': 'application/json' // 指定 JSON 格式
                                    },
                                    body: JSON.stringify(requestData2)
                                }
                            );
                            let json2= await responset2.json();
                            var prompt_id = json2.prompt_id
                            var t1 = setInterval(async function () {
                                try {
                                    var tresponse1 = await fetch('http://www.chenfuzhizao.com.cn/comfytask8288Not?prompt_id='+prompt_id+'&fuwuqi=8288');
                                    var data = await tresponse1.json();
                                    if(JSON.stringify(data) != '{}'){
                                        const specificId = prompt_id;
                                        const status1 = data[specificId]?.status
                                        if (status1.completed == true) {
                                            clearInterval(t1)
                                            const outputsForId = data[specificId]?.outputs;
                                            const imagesForEight = outputsForId?.["20"]?.images || outputsForId?.["30"]?.images;
                                            const filename = imagesForEight && imagesForEight.length > 0 ? imagesForEight[0].filename : null;
                                            let url2="http://117.131.189.172:8085/view?filename="+filename+"&subfolder=&type=temp";
                                            let encodedUrl2 = encodeURIComponent(url2);
                                            var response2 = await fetch(`http://www.chenfuzhizao.com.cn/downloadmyurl?url2=`+encodedUrl2)
                                            let json2=await response2.json();
                                            var path2 =  json2.outputPath
                                            var outpath = 'http://www.chenfuzhizao.com.cn/' + path2.replace("./output", "");
                                            console.log("输出抠图地址")
                                            console.log(outpath);
                                            let imm=await that.convertImageToBase64(outpath);
                                            that.imageFile=that.base64ToFile(imm,that.imageFileName)
                                            resolve('ok');
                                        }else{
                                            resolve('');
                                            throw new Error("抠图结果异常");
                                        }
                                    }
                                } catch (e) {
                                    that.$message.error("抠图失败");
                                    that.cutdown='';
                                    that.original='';
                                    clearInterval(t1)
                                    resolve('');
                                }
                            }, 2000)
                        } catch (e) {
                            this.$message.error("抠图失败");
                            resolve('');
                        }
                    });
                },


                base64ToFile(base64String, fileName) {
                    let arr = base64String.split(',');
                    let mime = arr[0].match(/:(.*?);/)[1];
                    let bstr = atob(arr[1]);
                    let n = bstr.length;
                    let u8arr = new Uint8Array(n);
                    while (n--) {
                        u8arr[n] = bstr.charCodeAt(n);
                    }
                    return new File([u8arr], fileName, { type: mime });
                },

                async convertImageToBase64(imageUrl) {
                    try {
                        // 使用 fetch 获取图片的二进制数据
                        const response = await fetch(imageUrl);

                        // 检查请求是否成功
                        if (!response.ok) {
                            throw new Error('Network response was not ok');
                        }

                        // 将二进制数据转换为 Blob
                        const blob = await response.blob();

                        // 使用 FileReader 将 Blob 转换为 Base64 编码
                        const reader = new FileReader();
                        reader.readAsDataURL(blob);

                        // 返回一个 Promise，当读取完成时解析为 Base64 数据
                        return new Promise((resolve, reject) => {
                            reader.onloadend = () => {
                                resolve(reader.result);
                            };
                            reader.onerror = () => {
                                reject(new Error('Failed to read the image as Base64'));
                            };
                        });
                    } catch (error) {
                        console.error('Error converting image to Base64:', error);
                        return null;
                    }
                },
            },

        });



        function scrollModels(direction) {
            // const container = document.querySelector('.model-card-container');
            // const cardWidth = document.querySelector('.model-card').offsetWidth;
            // const scrollAmount = cardWidth + 10; // 10 是卡片之间的间距

            // if (direction === 'left') {
            //     container.scrollBy({ left: -scrollAmount, behavior: 'smooth' });
            // } else if (direction === 'right') {
            //     container.scrollBy({ left: scrollAmount, behavior: 'smooth' });
            // }
             const container = document.querySelector('.model-card-container');
        const scrollAmount = 220; // Adjust based on your card width and margin

        if (direction === 'left') {
            container.scrollBy({ left: -scrollAmount, behavior: 'smooth' });
        } else {
            container.scrollBy({ left: scrollAmount, behavior: 'smooth' });
        }

        // Check if we need to loop the scroll
        if (container.scrollLeft === 0 && direction === 'left') {
            container.scrollTo({ left: container.scrollWidth, behavior: 'smooth' });
        } else if (container.scrollLeft + container.clientWidth >= container.scrollWidth && direction === 'right') {
            container.scrollTo({ left: 0, behavior: 'smooth' });
        }
        }


        let isDragging = false;
        let startX, startY;

        document.querySelectorAll(".canvas-wrapper canvas").forEach(canvas => {
            canvas.addEventListener("mousedown", (event) => {
                isDragging = false; // 初始假设未拖动
                startX = event.clientX;
                startY = event.clientY;
            });

            canvas.addEventListener("mousemove", (event) => {
                if (Math.abs(event.clientX - startX) > 5 || Math.abs(event.clientY - startY) > 5) {
                    isDragging = true; // 发生了明显拖动
                }
            });

            canvas.addEventListener("mouseup", (event) => {
                if (!isDragging) {
                    // 只有未拖动时才执行打开链接逻辑
                    let modelUrl = canvas.getAttribute("data-url");
                    let modelPath = canvas.getAttribute("data-path");
                    if (modelUrl && modelPath) {
                        openModelInNewTab(modelUrl, modelPath);
                    }
                }
            });

            canvas.addEventListener("mouseleave", () => {
                isDragging = false; // 鼠标离开时重置拖动状态
            });
        });


        function openModelInNewTab(url,link,type) {
            window.open(url, '_blank');
            if(!type){
                localStorage.glbUrl=link;
            }
        }
    </script>
</body>
</html>
<script type="module" src="./public/js/model-viewer.min.js"></script>
<style>
    .login-dialog {
        border-radius: 10px; /* 设置对话框边框圆角 */
    }

    .login-dialog1 {
        height: 60%;
    }

    .custom-title {
        color: black;
        font-size: 32px;
        font-weight: 700;
        margin-top: 30px;
    }

    .form-section {
        text-align: center;
    }

    .form-label {
        display: block;
        margin-bottom: 5px;
        font-weight: bold;
        text-align: left;
    }
    .custom-modal{
        opacity:1;
    }

    .button-icon {
        width: 16px;      /* 根据需要调整图标大小 */
        height: 16px;
        margin-left: 8px; /* 调整与文本之间的间距 */
        vertical-align: middle;
    }

</style>
